package net.towee.client.managers.impl;

import net.towee.client.event.core.UserRoleChangedEvent;
import net.towee.client.managers.AccountHelper;
import net.towee.client.managers.GroupsManager;
import net.towee.client.managers.RolesManager;
import net.towee.model.account.AccountPermission;
import net.towee.model.account.Role;
import net.towee.model.group.GroupData;
import net.towee.model.utils.Pair;
import net.towee.server.rpc.services.ToweeServiceAsync;

import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.inject.Inject;

public class RolesManagerImpl implements RolesManager {

	private final HandlerManager eventBus;
	private final AccountHelper account;
	private final ToweeServiceAsync service;
	private final GroupsManager groupsManager;

	@Inject
	public RolesManagerImpl(ToweeServiceAsync service, HandlerManager eventBus,
			AccountHelper accountHelper, GroupsManager groupsManager) {
		this.service = service;
		this.account = accountHelper;
		this.eventBus = eventBus;
		this.groupsManager = groupsManager;

		addHandler();
	}

	private void addHandler() {
		service.onUserRoleUpdated(null, null, new AsyncCallback<Pair<Role, String>>() {
			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(Pair<Role, String> result) {
				// Change role in local cache
				account.getAccountGroup(result.getSecond()).setRole(result.getFirst());

				// Fire an event
				eventBus.fireEvent(new UserRoleChangedEvent(result.getFirst(), account.getAccount()
						.getId(), result.getSecond()));
			}
		});
	}

	@Override
	public void addRole(String groupId, Role role, AsyncCallback<Role> handler) {
		// TODO Auto-generated method stub

	}

	@Override
	public void updateRole(String groupId, Role role, AsyncCallback<Boolean> handler) {
		// TODO Auto-generated method stub

	}

	@Override
	public void removeRole(String groupId, Role role, AsyncCallback<Boolean> handler) {
		// TODO Auto-generated method stub

	}

	@Override
	public void setDefaultRole(String groupId, Role role, final AsyncCallback<Void> handler) {
		Preconditions.checkNotNull(role, "null role");
		Preconditions.checkArgument(!Strings.isNullOrEmpty(role.getId()), "null role id");
		Preconditions.checkArgument(!Strings.isNullOrEmpty(groupId), "null group id");
		Preconditions.checkArgument(account.hasPermissions(groupId,
				AccountPermission.CAN_CHANGE_ROLES));
		
		service.setDefaultRole(groupId, role, new AsyncCallback<Void>(){
			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(Void result) {
				handler.onSuccess(result);
			}
		});
	}

	@Override
	public void applyRoleToUser(final Role role, final String userId, final String groupId,
			final AsyncCallback<Void> handler) {
		Preconditions.checkNotNull(role, "null role");
		Preconditions.checkArgument(!Strings.isNullOrEmpty(role.getId()), "null role id");
		Preconditions.checkArgument(!Strings.isNullOrEmpty(userId), "null user id");
		Preconditions.checkArgument(!Strings.isNullOrEmpty(groupId), "null group id");
		Preconditions.checkArgument(account.hasPermissions(groupId,
				AccountPermission.CAN_CHANGE_ACCOUNT_GROUP));

		service.applyRoleToUser(role.getId(), userId, groupId, new AsyncCallback<Boolean>() {
			@Override
			public void onFailure(Throwable caught) {
			}

			@Override
			public void onSuccess(Boolean result) {
				Preconditions.checkArgument(result, "fail apply role");

				// Change role in local cache
				account.getAccountGroup(groupId).setRole(role);

				// Fire an event
				eventBus.fireEvent(new UserRoleChangedEvent(role, userId, groupId));

				// Invoke handler
				handler.onSuccess(null);
			}
		});
	}

}
